

#include "glfw_simple.h"

extern void draw();

static int numframes = 0;

static float moveToX, moveToY;
static float mousx, mousy;
static unsigned int bstatus;
static char keystatus[256];

//static void draw(); // fwd decl
static void init(); // fwd decl

static float tx,ty;
static float textW, textH;

//static double mspf = 0.0;

#define MAX_LINES 16384

/*
struct line{
	float x0,y0,x1,y1;
};
*/

struct color{
	float r,g,b;
};

static struct color currentColor;

//struct sphere{
//	float x,y,segs,filled;
//}

//static struct line lines[MAX_LINES];
static int lineCount = 0;

static struct color lineColors[2*MAX_LINES];
static int colorCount = 0;

void setCol(float r, float g, float b)
{
	currentColor.r = r;
	currentColor.g = g;
	currentColor.b = b;
}

void moveTo(float x, float y)
{
    moveToX = x;
    moveToY = y;
}

/*
struct line makeLine(float x0,float y0,float x1,float y1)
{
	struct line tmp;
	tmp.x0 = x0; tmp.y0 = y0; tmp.x1 = x1; tmp.y1 = y1;
	return tmp;	
}
*/

void lineTo(float x, float y)
{	
    glBegin(GL_LINES);
        glVertex2f(moveToX, moveToY);
        glVertex2f(x,y);
    glEnd();
    moveToX = x;
    moveToY = y;
		/*
		if(lineCount >= MAX_LINES) return;

		lines[lineCount++] = makeLine(moveToX,moveToY,x,y);
		lineColors[colorCount++] = currentColor;
		lineColors[colorCount++] = currentColor;
    moveToX = x;
    moveToY = y;
		*/
}



void drawSph(float x, float y, float radi)
{
    if(radi < 0)
    {
        radi*=-1;
        glBegin(GL_LINE_LOOP);
    } else{
        glBegin(GL_POLYGON);
    }
    int segs = 18;
    // increase segments with radius
    if( fabs(radi) > 50) segs += 6;
    if( fabs(radi) > 150) segs += 9;
    
    int i;
    for(i=0; i<segs; i++)
    {
        glVertex2f(x+cos(i*2*M_PI/segs)*radi, y+sin(i*2*M_PI/segs)*radi );
    }
    glEnd();   
}

void drawCone(double x0,double y0,double r1,double x1,double y1,double r2)
{
    glBegin(GL_POLYGON);
        double ang = M_PI/2+atan2( y0-y1, x0-x1 );
        int segs = 12;
        for(int i=0; i<segs+1; i++){
           double a = ang+i*M_PI/(double)segs;
           double x = cos(a)*r2;
           double y = sin(a)*r2;
           glVertex2f(x1+x,y1+y);
        }
        ang+= M_PI;
        for(int i=0; i<segs+1; i++){
           double a = ang+i*M_PI/(double)segs;
           double x = cos(a)*r1;
           double y = sin(a)*r1;
           glVertex2f(x0+x,y0+y);
        }
    glEnd();

}

void DrawRect(float sx, float sy, float wx, float wy)
{
   moveTo(sx, sy);
   lineTo(sx+wx, sy+0);

   moveTo(sx, sy+wy);
   lineTo(sx+wx, sy+wy);

   moveTo(sx, sy);
   lineTo(sx, sy+wy);

   moveTo(sx+wx, sy);
   lineTo(sx+wx, sy+wy);
}

float rnd()
{
    return (float)rand() / (float)RAND_MAX;
}

// how do i normalize rnd?
float nrnd()
{
    return 1.0f-(float)rand() / ((float)RAND_MAX/2);
}


/* new window size or exposure */
void GLFWCALL reshape(int width, int height)
{
    //glfwSetWindowSize((int)xres, (int)yres);

    xres = (float)width;
    yres = (float)height;

    glViewport( 0, 0, width, height );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    glOrtho( 0.0, width, height, 0.0, -1.0, 1.0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
}

#define klock() glfwGetTime()
/*
double klock()
{
    return glfwGetTime();
}
*/

// no release callback :(
// freeglut has ! use it instead!
void GLFWCALL HandleKeys(int k, int status)
{        
  keystatus[k] = status;
}


void drawChar(int c,float scale){
   int verts = simplex[c][0];
   //float spacing = simplex[c][1];
   
   float ax = simplex[c][2];
   float ay = simplex[c][3]; 
   moveTo(tx+ax*scale-scale*2, ty-ay*scale+scale*2);  
   int i=0;
	 for(i=4; i<verts*2; i+=2)
   {
      ax = simplex[c][i+0];
      ay = simplex[c][i+1];

      if(ax==-1 || ay == -1) moveTo(tx+simplex[c][i+2]*scale-scale*2, ty-simplex[c][i+3]*scale+scale*2);
      else lineTo(tx+ax*scale-scale*2, ty-ay*scale+scale*2);        
   }
   lineTo(tx+simplex[c][i+0]*scale-scale*2,ty-simplex[c][i+1]*scale+scale*2);
}


void setFont(float w, float h)
{
	textW = w/20; textH = h/20;
}

void glPrintf(const char *format,...)
{
    if (format == NULL) return;
    float sx = moveToX;
    //float sy = moveToY;
    tx=moveToX;
    ty=moveToY;

    char finalText[256];

    va_list args;
    va_start(args, format);
    vsprintf(finalText, format, args);
    va_end(args);

    int len;
    int i;
            len = (int) strlen(finalText);
            for (i = 0; i < len; i++) {
                    if( finalText[i] == '\n' )
                    {
                            tx = sx;
                            ty += 40*textH;
                    }else{
                            int c = (int)finalText[i]-32;
                            if(c < 0 || c > 94) return;
                            {
                                    drawChar( c, textW );
                                    tx += simplex[c][1]*textW;
                            }
                    }
            }
    moveToX = sx;
    moveToY = ty;

}



/*
   Handle mouse events
*/
void GLFWCALL HandlePress(int button,int action)
{
    if (action == GLFW_PRESS)
    {
        if (button == GLFW_MOUSE_BUTTON_LEFT) bstatus = bstatus | 1;
        if (button == GLFW_MOUSE_BUTTON_MIDDLE) bstatus = bstatus | 4;
        if (button == GLFW_MOUSE_BUTTON_RIGHT)  bstatus = bstatus | 2;
    } 
    if (action == GLFW_RELEASE) 
    {
        if (button == GLFW_MOUSE_BUTTON_LEFT) bstatus = bstatus & ~1;
        if (button == GLFW_MOUSE_BUTTON_MIDDLE) bstatus = bstatus & ~4;
        if (button == GLFW_MOUSE_BUTTON_RIGHT)  bstatus = bstatus & ~2;        
    }
}

void GLFWCALL HandleMouseMotion(int x, int y)
{
    mousx = x;
    mousy = y;
}

void doPrint(int i)
{
      //if(keystatus[i]) setfont(8,14); else setfont(8,12);
		if( keystatus[i] ){ 
			setFont(.35f,.35f);	
			setCol(1,1,0);    
			glColor3f(1,1,0); 
			glPrintf("\nk[%i] = on", i );
		}
		else{
			setFont(.3f,.3f);	
			setCol(1,1,1);   	
			glColor3f(1,1,1); 
			glPrintf("\nk[%i] = off", i );
		}
}

void showk()
{
   int perline = 35;   
	 int i=0;
   moveTo(0,0);
   for(i=0; i<perline;i++){
      doPrint(i);
   }
   moveTo(xres*.2,0);
   for(i=perline; i<perline*2;i++){
      doPrint(i);
   }
   moveTo(xres*.4,0);
   for(i=perline*2; i<perline*3;i++){
      doPrint(i);
   }
   moveTo(xres*.6,0);
   for(i=perline*3; i<perline*4;i++){
      doPrint(i);
   }
   moveTo(xres*.8,0);
   for(i=perline*4; i<perline*5;i++){
			doPrint(i);
   }   

}
/*
void drawBufferedLines()
{
			lineCount--; // is incremented 1 to much in lineTo.
			glEnableClientState(GL_VERTEX_ARRAY);
			glEnableClientState(GL_COLOR_ARRAY);

			glColorPointer(3,GL_FLOAT,0,lineColors);
			glVertexPointer(2,GL_FLOAT,0,lines); 
		
			glDrawArrays(GL_LINES, 0, 2*lineCount ); // v1 and v2
			
			glDisableClientState(GL_VERTEX_ARRAY);
			glDisableClientState(GL_COLOR_ARRAY);
			lineCount = 0;
			colorCount = 0;
}
*/

/*
int main()//int argc, char *argv[]
{
    int w = 1280; int h = 800;
    xres = w;
    yres = h;
    
    glfwInit();
    glfwSetWindowSizeCallback(reshape);
    glfwOpenWindowHint(GLFW_WINDOW_NO_RESIZE, GL_FALSE);
    if( !glfwOpenWindow(w,h,0,0,0,0,24,0,GLFW_WINDOW) )
		{
			glfwTerminate();
			return 1;
		}
		reshape(w,h);
		glfwSetWindowTitle("glfwSimple by Torbjoern 2010");
		glfwSetMousePosCallback(HandleMouseMotion);
		glfwSetMouseButtonCallback(HandlePress);
		glfwSetKeyCallback(HandleKeys);
		

    int i=0;
    for(i=0; i<256; i++)
        keystatus[i] = 0;

    glEnable(GL_POINT_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

                init();
		//glfwEnable(GLFW_AUTO_POLL_EVENTS);
		while( !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED) )
		{
			draw();
			
			//double frameStart = klock();
			
			//glClear(GL_COLOR_BUFFER_BIT);
			//glColor3f(1,1,1);		

			
			//showk();	

			//float siz = bstatus==1 ? 100 : -100;
			//drawSph(mousx,mousy,siz);
			//drawSph(xres/2,yres/2+sin(klock())*50.0f,-100);

			//glColor3f(1,0,0); glRectf(mousx-30,mousy-15,mousx+30,mousy+15);
			//glColor3f(1,1,1);
			//setFont(.5f,.5f);
			//moveTo(xres/2,yres/2);
			//glPrintf("MSPF = %.4f",(float)mspf);  
			

			//moveTo(xres/2,yres/2);
			//glPrintf("its a beautiful day!\nNEWLINE\n%.2f",3.14159);  
			//moveTo(15,30);			
			//glPrintf("frames %i",numframes);  


			//drawBufferedLines();
			numframes++;

			GLenum err = glGetError();
		 	//if(err == GL_NO_ERROR ) printf("yay\n");
			if(err == GL_INVALID_ENUM ) printf("err: ENUM\n");
			if(err == GL_INVALID_VALUE ) printf("err: VALUE\n");
			if(err == GL_INVALID_OPERATION ) printf("err: OPERATION\n");
			if(err == GL_STACK_OVERFLOW ) printf("err: OVERFLOW\n");
			if(err == GL_STACK_UNDERFLOW ) printf("err: UNDERFLOW\n");
			if(err == GL_OUT_OF_MEMORY ) printf("err: MEMORY\n");

			glfwSwapBuffers();
			//glfwSleep(16.0/1000.0);

			//mspf = klock() - frameStart;
		}
		glfwTerminate();
    return 0;
}*/

